package com.pangu.core.engine.game;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.pangu.core.BMDataContext;
import com.pangu.core.cache.CacheConfigTools;
import com.pangu.core.cache.CacheHelper;
import com.pangu.core.engine.game.impl.RedBlackGame;
import com.pangu.core.engine.game.model.PlayerRecordHonghei;
import com.pangu.core.engine.game.task.redblack.CreateRedBlackAITask;
import com.pangu.core.engine.game.task.redblack.CreateRedBlackAllCardsTask;
import com.pangu.core.nettyserver.client.NettyClients;
import com.pangu.core.nettyserver.handler.BeiMiClient;
import com.pangu.util.AIBet;
import com.pangu.util.PlayerUtils;
import com.pangu.util.TimeUtil;
import com.pangu.util.UKTools;
import com.pangu.util.disruptor.DisruptorHandler;
import com.pangu.util.rules.model.Board;
import com.pangu.util.rules.model.GameHistoryBoard;
import com.pangu.util.rules.model.RedBlackStatus;
import com.pangu.util.rules.model.TopPlayer;
import com.pangu.web.model.GamePlayway;
import com.pangu.web.model.GameRoom;
import com.pangu.web.model.PlayUserClient;
import com.pangu.web.model.SysGameConfig;
import com.pangu.web.service.repository.jpa.GameRoomRepository;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * Description:红黑大战游戏引擎
 *
 * @author abo
 * @date 2018年3月30日
 */
@Slf4j
@Service(value = "redBlcakGameEngine")
public class RedBlackGameEngine {

	public static String gameStatus;// 1开始下注，2停止下注，3结算
	public static Date exeDate;// 状态执行时间

	/**
	 * 
	 * Description: 初始化然后创建房间，创建机器人
	 * 
	 * @author abo
	 * @date 2018年4月6日
	 */
	public void initRedBlcakGameEngine(String playWay, String orgi) {
		// BMDataContext.getGameEngine().dismissRoom(gameRoom, userid, orgi);
		GamePlayway gamePlayway = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(playWay, orgi);
		if (gamePlayway == null) {
			log.error(new Date() + "-------------------没有获取到红黑玩法");
			// return;
		} else {
			log.info(new Date() + "-------------------初始化红黑房间开始");
			// 初始化房间，先通过玩法去队列里面拿没有的话创建一个。
			GameRoom gameRoom = CacheHelper.getQueneCache().get(gamePlayway.getId(), gamePlayway.getOrgi());
			if (gameRoom == null) {
				gameRoom = this.creatGameRoom(gamePlayway);
			}
			gameRoom.setGamePlayway(gamePlayway);
			gameRoom.setPlayers(gamePlayway.getPlayers());
			CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, gameRoom.getOrgi());

			log.info("--------------------------红黑房间开始加入ai");
			// 根据房间人数，补加入ai
			SysGameConfig gameConfig = CacheConfigTools.getSysGameConfig(gameRoom.getOrgi());
			if (gameConfig.isEnableai()) {
				new CreateRedBlackAITask(0, gameRoom, gameRoom.getOrgi()).execute();
			}

			// 开始游戏
			startGame(gameRoom, gamePlayway);
		}
	}

	/**
	 * 
	 * Description: 开始游戏
	 * 
	 * @author abo
	 * @date 2018年4月6日
	 * @param gameRoom
	 * @param gamePlayway
	 */
	public void startGame(GameRoom gameRoom, GamePlayway gamePlayway) {
		// 加一个timer事件，每个流程10秒执行一次，补ai，下注，开牌，结算
		log.info("开始游戏");
		gameStatus = "1";
		exeDate = new Date();
		// 下注
		log.info(exeDate + "--------------------------开始下注");
		// 红黑是3种下注类型
		AIBet.hongheiBet(gameRoom.getId(), gameRoom.getOrgi(), 3);
		// 像前端推送状态
		RedBlackStatus redBlackStatus = synRedBlackRoomStatus();
		// 把下注记录也推送过去
		List<PlayerRecordHonghei> playerRecordHongheis = getRoomAllPlayerRecord(gameRoom);
		redBlackStatus.setPlayerRecordHongheis(playerRecordHongheis);
		ActionTaskUtils.sendEvent("gamestatus", redBlackStatus, gameRoom);
		// 发牌
		RedBlackGame rbGame = new RedBlackGame();
		Board board = rbGame.process(gameRoom, gamePlayway, 3);
		CacheHelper.getBoardCacheBean().put(gameRoom.getId(), board, gameRoom.getOrgi());
		CacheHelper.getSystemCacheBean().put(gamePlayway.getId(), gamePlayway, gamePlayway.getOrgi());
		TimeUtil.countDown(12);// 开始下注12秒，然后翻牌
		gameStatus = "2";
		exeDate = new Date();
		// 像前端推送状态
		redBlackStatus = synRedBlackRoomStatus();
		ActionTaskUtils.sendEvent("gamestatus", redBlackStatus, gameRoom);
		log.info(exeDate + "--------------------------结束下注，开始翻牌");
		TimeUtil.countDown(6);// 6秒翻牌，然后结算
		// 结算
		new CreateRedBlackAllCardsTask(0, gameRoom, gameRoom.getOrgi()).execute();
		gameStatus = "3";
		exeDate = new Date();
		// 像前端推送状态
		redBlackStatus = synRedBlackRoomStatus();
		ActionTaskUtils.sendEvent("gamestatus", redBlackStatus, gameRoom);
		// 返回前台同步金额
		log.info(exeDate + "--------------------------结算完成4秒后开始游戏");
		TimeUtil.countDown(4);
//		gameStatus = "1";
//		exeDate = new Date();
		// 像前端推送状态
//		redBlackStatus = synRedBlackRoomStatus();
//		ActionTaskUtils.sendEvent("gamestatus", redBlackStatus, gameRoom);
		// 更新排名
		TopPlayer topPlayer = updateTop(gameRoom);
		// 取前6个然后推送给前端
		topPlayer = initPlayerPosition(topPlayer, 6);
		ActionTaskUtils.sendEvent("initPlayerPosition", topPlayer, gameRoom);
		// 重新开始游戏
		startGame(gameRoom, gameRoom.getGamePlayway());
	}

	/**
	 * 
	 * Description:重新初始化座位人员数量
	 * 
	 * @author abo
	 * @date 2018年5月15日
	 * @param topPlayer
	 * @param i
	 * @return
	 */
	private TopPlayer initPlayerPosition(TopPlayer topPlayer, int i) {
		List<PlayUserClient> playUserClients = topPlayer.getPlayer();
		topPlayer.setPlayer(playUserClients.subList(0, i));
		return topPlayer;
	}

	/**
	 * 
	 * Description: 程序启动就开始初始化房间，传入玩法
	 * 
	 * @author abo
	 * @date 2018年3月30日
	 * @param playway
	 * @return
	 */
	private GameRoom creatGameRoom(GamePlayway playway) {
		GameRoom gameRoom = new GameRoom();
		gameRoom.setCreatetime(new Date());
		gameRoom.setRoomid(UKTools.getUUID());
		gameRoom.setUpdatetime(new Date());
		gameRoom.setMaster(gameRoom.getRoomid());
		// 玩法不等于空的时候
		if (playway != null) {
			gameRoom.setPlayway(playway.getId());
			gameRoom.setRoomtype(playway.getRoomtype());
			gameRoom.setPlayers(playway.getPlayers());
		}
		gameRoom.setPlayers(playway.getPlayers());
		gameRoom.setCardsnum(playway.getCardsnum());
		gameRoom.setCurpalyers(1);
		gameRoom.setCardroom(false);// 是否是房卡模式
		gameRoom.setStatus(BeiMiGameEnum.CRERATED.toString());
		gameRoom.setCurrentnum(0);
		// gameRoom.setCreater(userid);
		gameRoom.setNumofgames(0); // 无限制
		gameRoom.setOrgi(playway.getOrgi());
		gameRoom.setRoomtype(BMDataContext.ModelType.HALL.toString());

		// 未达到最大玩家数量，加入到游戏撮合 队列，继续撮合
		CacheHelper.getQueneCache().put(gameRoom, playway.getOrgi());
		GameRoomRepository gameRoomRepository = BMDataContext.getContext().getBean(GameRoomRepository.class);
		DisruptorHandler.published(gameRoom, null, gameRoomRepository, BMDataContext.UserDataEventType.SAVE.toString());

		return gameRoom;
	}

	/**
	 * 
	 * Description: 玩家加入房间
	 * 
	 * @author abo
	 * @date 2018年3月27日
	 * @param gameRoom
	 * @param playUser
	 * @param playerList
	 */
	public void joinRoom(GameRoom gameRoom, PlayUserClient playUser, List<PlayUserClient> playerList) {
		boolean inroom = false;
		for (PlayUserClient user : playerList) {
			if (user.getId().equals(playUser.getId())) {
				inroom = true;
				break;
			}
		}
		if (inroom == false) {
			playUser.setPlayerindex(System.currentTimeMillis());
			playUser.setGamestatus(BMDataContext.GameStatusEnum.PLAYING.toString());
			playUser.setPlayertype(BMDataContext.PlayerTypeEnum.NORMAL.toString());
			playUser.setRoomid(gameRoom.getId());
			playUser.setRoomready(false);

			playerList.add(playUser);
			NettyClients.getInstance().joinRoom(playUser.getId(), gameRoom.getId());
			// 将用户加入到 room MultiCache
			CacheHelper.getGamePlayerCacheBean().put(playUser.getId(), playUser, playUser.getOrgi());
			CacheHelper.getApiUserCacheBean().put(playUser.getId(), playUser, playUser.getOrgi());
		}

		/**
		 * 不管状态如何，玩家一定会加入到这个房间
		 */
		CacheHelper.getRoomMappingCacheBean().put(playUser.getId(), gameRoom.getId(), playUser.getOrgi());
	}

	/**
	 * 
	 * Description: 进入房间请求
	 * 
	 * @author abo
	 * @date 2018年4月6日
	 * @param userid
	 * @param playway
	 * @param room
	 * @param orgi
	 * @param userClient
	 * @param beiMiClient
	 */
	public void gameRequest(String userid, String playway, GameRoom room, String orgi, PlayUserClient userClient,
			BeiMiClient beiMiClient) {
		/**
		 * 如果当前房间到达了最大玩家数量，则不再加入到 撮合队列
		 */
		List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(room.getId(),
				room.getOrgi());

		// 加入房间
		this.joinRoom(room, userClient, playerList);

		/**
		 * 游戏状态 ， 玩家请求 游戏房间，活动房间状态后，发送事件给 StateMachine，由 StateMachine驱动 游戏状态 ，
		 * 此处只负责通知房间内的玩家 1、有新的玩家加入
		 * 2、给当前新加入的玩家发送房间中所有玩家信息（不包含隐私信息，根据业务需求，修改PlayUserClient的字段，剔除掉隐私信息后发送）
		 */
		// ActionTaskUtils.sendEvent("joinroom", new JoinRoom(userClient, 0,
		// room.getPlayers(), room), room);
		// 像前端推送状态
		RedBlackStatus redBlackStatus = synRedBlackRoomStatus();
		// 把下注记录也推送过去
		List<PlayerRecordHonghei> playerRecordHongheis = getRoomAllPlayerRecord(room);
		redBlackStatus.setPlayerRecordHongheis(playerRecordHongheis);
		ActionTaskUtils.sendEvent("gamestatus", redBlackStatus, room);
		/**
		 * 发送给单一玩家的消息
		 */
		ActionTaskUtils.sendPlayers(beiMiClient, room);

	}

	/**
	 * 
	 * Description: 更新排行情况
	 * 
	 * @author abo
	 * @date 2018年4月10日
	 * @param roomId
	 * @param orgi
	 */
	private TopPlayer updateTop(GameRoom gameRoom) {
		List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(),
				gameRoom.getOrgi());
		// 初始化排行榜数据
		ArrayList<PlayUserClient> list = new ArrayList<>();
		for (PlayUserClient playUserClient : playerList) {
			if (playUserClient.isBlank()) {
				list.add(playUserClient);
				break;
			}
		}
		list.addAll(PlayerUtils.getNewTopPlayersByMoney(playerList, gameRoom.getPlayers()));
		TopPlayer top = new TopPlayer();
		top.setPlayer(list);
		CacheHelper.getGamePlayerTopCacheBean().put(gameRoom.getId(), top, gameRoom.getOrgi());
		return top;
	}

	/**
	 * 
	 * Description: 同步状态
	 * 
	 * @author abo
	 * @date 2018年5月15日
	 * @param json
	 * @param playUserClient
	 * @return
	 */
	public RedBlackStatus synRedBlackRoomStatus() {
		RedBlackStatus redBlackStatus = new RedBlackStatus();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		redBlackStatus.setCommand("gamestatus");
		redBlackStatus.setExeDate(sdf.format(RedBlackGameEngine.exeDate));
		redBlackStatus.setGameStatus(RedBlackGameEngine.gameStatus);
		redBlackStatus.setStatus(1);
		redBlackStatus.setMessage("请求状态成功");
		return redBlackStatus;
	}

	/**
	 * 
	 * Description:获取房间所有的下注记录
	 * 
	 * @author abo
	 * @date 2018年5月15日
	 * @param gameRoom
	 * @return
	 */
	public List<PlayerRecordHonghei> getRoomAllPlayerRecord(GameRoom gameRoom) {
		List<PlayUserClient> plays = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(),
				gameRoom.getOrgi());
		List<PlayerRecordHonghei> newList = new ArrayList<PlayerRecordHonghei>();
		PlayerRecordHonghei playerRecordHonghei = null;
		for (PlayUserClient playUserClient : plays) {
			// 获取此用户的下注记录
			List<PlayerRecordHonghei> prList = (List<PlayerRecordHonghei>) CacheHelper.getGameRecordHongheiCacheBean()
					.getCacheObject(playUserClient.getId(), playUserClient.getOrgi());
			if (prList == null) {
				continue;
			}
			for (PlayerRecordHonghei entity : prList) {
				playerRecordHonghei = new PlayerRecordHonghei();
				playerRecordHonghei.setPlayerId(entity.getPlayerId());
				playerRecordHonghei.setCoin(entity.getCoin());
				playerRecordHonghei.setGameSubType(entity.getGameSubType());
				playerRecordHonghei.setSummaryId(playUserClient.getNickname());
				newList.add(playerRecordHonghei);
			}
		}
		return newList;
	}

	public JSONObject getHistoryBoards(String roomid, JSONObject json) {
		Object object = CacheHelper.getGameHistoryBoardCache().getCacheObject(roomid, BMDataContext.SYSTEM_ORGI);
		if (object != null) {
			List<GameHistoryBoard> list = (List<GameHistoryBoard>) object;
			for (GameHistoryBoard gameHistoryBoard : list) {
				gameHistoryBoard.setCreateTime(null);
				gameHistoryBoard.setId(null);
				gameHistoryBoard.setRoomId(null);
			}
			json.put("historyBoards", list);
		}
		return json;
	}
}
